package cn.zero.flowspringbootstater.service.impl;

import cn.zero.flowspringbootstater.configruation.TransactionManager;
import cn.zero.flowspringbootstater.configruation.FLowCurrentUserConfig;
import cn.zero.flowspringbootstater.configruation.IdFactory;
import cn.zero.flowspringbootstater.constant.Constrants;
import cn.zero.flowspringbootstater.constant.HttpStatus;
import cn.zero.flowspringbootstater.constant.SysConstant;
import cn.zero.flowspringbootstater.mapper.FlowEventsMapper;
import cn.zero.flowspringbootstater.mapper.FlowMapper;
import cn.zero.flowspringbootstater.modular.bean.*;
import cn.zero.flowspringbootstater.modular.bean.FlowErrorException;
import cn.zero.flowspringbootstater.modular.entity.*;
import cn.zero.flowspringbootstater.modular.vo.*;
import cn.zero.flowspringbootstater.service.*;
import cn.zero.flowspringbootstater.utils.CopyUtil;
import cn.zero.flowspringbootstater.utils.FunUtil;
import cn.zero.flowspringbootstater.utils.function.BranchHandler;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 审批流程 服务实现类
 * </p>
 *
 * @author lei
 * @since 2022-06-17
 */
@Slf4j
@RequiredArgsConstructor
@EnableConfigurationProperties(UserConfiguration.class)
public class FlowServiceImpl extends ServiceImpl<FlowMapper, Flow> implements IFlowService, InitializingBean {


    private final FlowBusinessServiceImpl flowBusinessService;
    private final FlowNodeServiceImpl flowNodeService;
    private final FlowEventsServiceImpl flowEventsService;
    private final FlowEventsMapper flowEventsMapper;
    private final FlowNodeUserServiceImpl flowNodeUserService;
    private final FLowCurrentUserConfig fLowCurrentUserConfig;
    private final IdFactory idFactory;
    private final TransactionManager tranManager;
    private final UserConfiguration userConfiguration;
    /**
     * 查询用户的详情
     *
     * @param userId:
     * @return: cn.ygkj.system.api.domain.SysUser
     * @author: lei
     */

    private FLowUser getSysUser(String userId) {

        FLowUser currentUser = fLowCurrentUserConfig.getCurrentUser();

        return currentUser;
    }

    /**
     * 获取当前登录用户
     *
     * @return cn.zero.flowspringbootstater.modular.bean.FLowUser
     * @author lei
     */

    private FLowUser getCurrentUser()   {

        if (!userConfiguration.getEnable()){
            log.debug("未开启审批流程功能");
            return null;
        }
        FLowUser currentUser = null;
        try {
            currentUser = fLowCurrentUserConfig.getCurrentUser();
            return currentUser;
        } catch (Exception e) {

            throw new FlowErrorException("请提供获取当前登录用的发方式");
        }


    }

    @Override
    public BranchHandler approvalFunc(FlowApprovalDto dto)  throws FlowErrorException {
        FlowApprovalRes approval = approval(dto);
        Boolean over = approval.getOver();
        return FunUtil.isTureOrFalse(over);
    }

    /**
     * 流程审批
     *
     * @param dto :  审批参数
     * @return: FlowApprovalRes 审批结果
     * @author: lei
     */
    @Override
    public FlowApprovalRes approval(FlowApprovalDto dto) throws FlowErrorException {
        String businessId = dto.getBusinessId();
        Long flowId = dto.getFlowId();
        String userId = dto.getUserId();
        String annexUrl = dto.getAnnexUrl();//附件路径
        String annexName = dto.getAnnexName();//附件名称
        String auditInfo = dto.getAuditInfo();//审批意见
        String flowStatus = dto.getFlowStatus();//审批是否通过

        //校验流程是否可用
        Flow flow = checkFlow(flowId);
        //查询该业务id的审批记录关联
        FlowBusiness flowBusinessHistory = flowBusinessService.lambdaQuery()
                .eq(FlowBusiness::getBusinessId, businessId)
                .eq(FlowBusiness::getState, SysConstant.whether.Yes)
                .eq(FlowBusiness::getFlowId, flowId).one();
        //查询当前审批到哪个节点了
        Long currentNodeId = flowBusinessHistory.getCurrentNodeId();
        FlowNode currentNode = flowNodeService.lambdaQuery().eq(FlowNode::getId, currentNodeId).one();
        //审批结束
        if (flowBusinessHistory.getFlowState().equals(Constrants.FlowState.OVER_APPRPVAL))
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "审批结束，无法进行下一步，请重新发起");


        //该节点有权限审批的用户列表
        List<FlowNodeUser> hasRoleUserList = flowNodeUserService.lambdaQuery().eq(FlowNodeUser::getNodeId, currentNodeId).list();
        List<String> exits = hasRoleUserList.stream().map(FlowNodeUser::getUserId).filter(f -> f.equals(userId)).collect(Collectors.toList());
        if (exits.size() == 0)
            throw new FlowErrorException(HttpStatus.FORBIDDEN, "当前用户无权限审批");

        //此流程已审核的事件集合
        List<FlowEvents> flowEventsHistory = flowEventsService.lambdaQuery()
                .eq(FlowEvents::getFlowNodeId, currentNodeId)
                .eq(FlowEvents::getOrderId, businessId)
                .eq(FlowEvents::getEventStatus, SysConstant.whether.Yes).list();

        //单审核还是并行多人审核
        String type = flow.getType();

        //构建返回参数
        FlowApprovalRes res = new FlowApprovalRes();
        res.setFlowId(flowId);
        res.setCurrentNodeId(currentNodeId);//初始化审批节点；审批之后变更为下一节点

        //单人
        if (type.equals(Constrants.FlowType.SINGLE)) {
            //此节点是否被其他人审核了
            FlowEvents flowEvented = flowEventsHistory.stream().filter(f -> f.getFlowNodeId().equals(currentNodeId)).findFirst().orElse(null);

            if (flowEvented != null)
                throw new FlowErrorException(HttpStatus.BAD_REQUEST, "单人审核流程中当前审批节点已被用户审核");
        }

        //多人
        if (type.equals(Constrants.FlowType.MULTIPLE)) {
            //判断此节点已审核的数据是否有不通过的
            FlowEvents flowEventsReject = flowEventsHistory.stream().filter(f -> f.getFlowStatus().equals(SysConstant.whether.No)).findFirst().orElse(null);
            if (flowEventsReject != null)
                throw new FlowErrorException(HttpStatus.BAD_REQUEST, "此审批流程审批状态为不通过，流程已结束，请重新发起审批");
            //查询当前审批人是否是此节点最后一个审批人
            //该节点已经审批的用户记录
            List<String> flowedUsers = flowEventsHistory.stream().map(FlowEvents::getUserId).collect(Collectors.toList());
            List<String> hasRoleUserIds = hasRoleUserList.stream().map(FlowNodeUser::getUserId).collect(Collectors.toList());
            List<String> notFlowed = hasRoleUserIds.stream().filter(f -> !flowedUsers.contains(f)).collect(Collectors.toList());
            //不是此节点的最后一个审批人
            if (!(hasRoleUserIds.size() - flowedUsers.size() == 1 && notFlowed.contains(userId))) {

                //插入t_flow_event审批数据
                FlowEvents flowEvents = new FlowEvents();
                flowEvents.setOrderId(businessId)
                        .setFlowStatus(flowStatus)
                        .setAuditDate(LocalDateTime.now())
                        .setAnnexName(annexName)
                        .setAnnexUrl(annexUrl)
                        .setAuditInfo(auditInfo)
                        .setUserId(userId)
                        .setFlowNodeId(currentNodeId)
                        .setEventStatus(SysConstant.whether.Yes);
                //返回参数

                boolean save = flowEventsService.save(flowEvents);
                res.setOver(Boolean.FALSE)
                        .setSuccess(save);
                return res;
            }
        }

        //有下一节点且审批通过
        if (flowStatus.equals(SysConstant.whether.Yes) && currentNode.getNextNodeId() != null) {
            //修改数据审核节点为下一节点
            flowBusinessHistory.setCurrentNodeId(currentNode.getNextNodeId())
                    .setFlowState(Constrants.FlowState.UNDER_APPROVAL);
            FlowEvents flowEvents = new FlowEvents();
            flowEvents.setOrderId(businessId)
                    .setFlowStatus(flowStatus)
                    .setAuditDate(LocalDateTime.now())
                    .setAnnexName(annexName)
                    .setAnnexUrl(annexUrl)
                    .setAuditInfo(auditInfo)
                    .setUserId(userId)
                    .setFlowNodeId(currentNodeId)
                    .setEventStatus(SysConstant.whether.Yes);

            Boolean success = tranManager.exe(() -> {
                boolean updateNum = flowBusinessService.updateById(flowBusinessHistory);
                boolean save = flowEventsService.save(flowEvents);
                return updateNum && save;
            });
            //插入t_flow_event审批数据

            //构建返回参数
            res.setOver(Boolean.FALSE)
                    .setCurrentNodeId(currentNode.getNextNodeId())
                    .setSuccess(success);
            return res;
        }
        //没有下一节点或审批结果为不通过
        flowBusinessHistory.setFlowState(Constrants.FlowState.OVER_APPRPVAL);//不改变审批节点

        //插入t_flow_event审批数据
        FlowEvents flowEvents = new FlowEvents();
        flowEvents.setOrderId(businessId)
                .setFlowStatus(flowStatus)
                .setAuditDate(LocalDateTime.now())
                .setAnnexName(annexName)
                .setAnnexUrl(annexUrl)
                .setAuditInfo(auditInfo)
                .setUserId(userId)
                .setFlowNodeId(currentNodeId)
                .setEventStatus(SysConstant.whether.Yes);

        Boolean success = tranManager.exe(() -> {
            boolean updateNum = flowBusinessService.updateById(flowBusinessHistory);
            boolean save = flowEventsService.save(flowEvents);
            return updateNum && save;
        });

        //构建返回参数
        res.setOver(Boolean.TRUE)
                .setSuccess(success);
        return res;
    }

    /**
     * 校验流程是否可用
     *
     * @param flowId: 流程id
     * @return: cn.ygkj.system.entity.Flow
     * @author: lei
     */


    private Flow checkFlow(Long flowId) throws FlowErrorException{
        //校验流程是否存在
        Flow flow = this.lambdaQuery().eq(Flow::getId, flowId).last("limit 1").one();
        if (flow == null)
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "流程不存在");

        if (flow.getStatus().equals(SysConstant.whether.No))
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "流程未启用");
        return flow;
    }

    /**
     * 绑定/重新发起业务审批流程
     *
     * @param dto :
     * @return: cn.ygkj.system.api.dto.FlowApprovalRes
     * @author: lei
     */
    @Override
    public FlowBindRes bindFlow(FlowBindDto dto) throws FlowErrorException {

        checkParams(dto);

        String businessId = dto.getBusinessId();
        Long flowId = dto.getFlowId();
        //校验流程是否存在且可用
        Flow flow = this.lambdaQuery()
                .eq(Flow::getId, flowId)
                .eq(Flow::getStatus, SysConstant.whether.Yes)
                .last("limit 1")
                .oneOpt()
                .orElseThrow(() -> new FlowErrorException(HttpStatus.BAD_REQUEST, "流程不存在或被禁用"));

        //校验此订单的此流程是否存在
        FlowBusiness flowBusiness = flowBusinessService.lambdaQuery()
                .eq(FlowBusiness::getBusinessId, businessId)
                .eq(FlowBusiness::getFlowId, flowId)
                .eq(FlowBusiness::getState, SysConstant.whether.Yes).last("limit 1").one();

        //查询改审核流程的初始审批节点
        FlowNode firstNode = flowNodeService.lambdaQuery()
                .eq(FlowNode::getFlowId, flowId)
                .orderByAsc(FlowNode::getOrderBy)
                .last("limit 1").oneOpt().orElseThrow(() -> new FlowErrorException(HttpStatus.BAD_REQUEST, "流程节点未配置"));

        //不存在则发起审批流程
        FlowBindRes res;

        if (flowBusiness == null) {
            res = firstBind(dto, firstNode, flow.getType());
        } else {
            res = reBind(dto, flowBusiness, firstNode, flow.getType());
        }

        return res;
    }

    /**
     * 重新发起流程审批
     *
     * @param dto
     * @param flowBusiness
     * @param firstNode
     * @param type
     * @return cn.ygkj.system.api.dto.FlowBindRes
     * @author lei
     */
    private FlowBindRes reBind(FlowBindDto dto, FlowBusiness flowBusiness, FlowNode firstNode, String type) throws FlowErrorException {
        String businessId = flowBusiness.getBusinessId();
        Long flowId = dto.getFlowId();
        FlowBindRes res = new FlowBindRes();
        res.setType(type);
        res.setCurrentNodeId(firstNode.getNextNodeId());

        //存在则重新绑定审批流程
        //查询该审批流程是否结束或者为不通过且生效中，
        if (!flowBusiness.getFlowState().equals(Constrants.FlowState.REJECT_APPROVAL)
                && flowBusiness.getFlowState().equals(SysConstant.whether.Yes))
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "该数据正在审批中，无法重新发起审批");

        flowBusiness.setFlowState(Constrants.FlowState.UNDER_APPROVAL)
                .setCurrentNodeId(firstNode.getNextNodeId());
        QueryWrapper<FlowBusiness> updateWrapper = new QueryWrapper<>();
        updateWrapper.lambda().eq(FlowBusiness::getId, flowBusiness.getId());
        //修改业务表数据状态
        //重置审批事件表该业务的审批数据
        Boolean success = tranManager.exe(() -> flowBusinessService.getBaseMapper().update(flowBusiness, updateWrapper) > 0 && flowEventsMapper.updateByFowId2BusinessId(businessId, flowId, "0") > 0);
        res.setSuccess(success);

        return res;
    }

    /**
     * 发起流程绑定
     *
     * @param dto
     * @param firstNode
     * @param type
     * @return cn.ygkj.system.api.dto.FlowBindRes
     * @author lei
     */

    private FlowBindRes firstBind(FlowBindDto dto, FlowNode firstNode, String type) {
        Long flowId = dto.getFlowId();
        String businessId = dto.getBusinessId();
        String initUserId = dto.getInitUserId();

        //封住绑定流程结果初始化
        FlowBindRes res = new FlowBindRes();
        res.setType(type);
        res.setCurrentNodeId(firstNode.getNextNodeId());
        //初始化当前事件的流程号、当前节点、审批状态、审批
        FlowBusiness flowBusiness = new FlowBusiness();
        flowBusiness.setBusinessId(businessId)
                .setFlowId(flowId)
                .setBusinessId(businessId)
                .setFlowState(Constrants.FlowState.UNDER_APPROVAL)
                .setCurrentNodeId(firstNode.getNextNodeId())
                .setState(SysConstant.whether.Yes);


        //保存用户审批事件
        FlowEvents flowEvents = new FlowEvents();
        flowEvents.setFlowStatus(SysConstant.whether.Yes)
                .setOrderId(businessId)
                .setEventStatus(SysConstant.whether.Yes)
                .setAuditDate(LocalDateTime.now())
                .setFlowNodeId(firstNode.getId())
                .setUserId(initUserId)
                .setAuditInfo("发起申请");

        flowEvents.setAuditDate(LocalDateTime.now());
        Boolean success = tranManager.exe(() -> flowBusinessService.save(flowBusiness) && flowEventsService.save(flowEvents));
        res.setSuccess(success);
        return res;
    }


    /**
     * 获取业务数据的审批状态-
     *
     * @param businessId :
     * @return: 返回一个当前业务所绑定的审批流程集合
     * @author: lei
     */
    @Override
    public FlowApprovalRes flowState(String businessId) {

        return null;
    }

    //编辑流程
    @Override
    public Long editFlow(FlowParamVo flowParamVo) throws FlowErrorException {
        Long id = flowParamVo.getId();
        if (id == null)
            return addFlow(flowParamVo);

        return updateFlow(flowParamVo);

    }

    /**
     * 新增流程节点
     * @param flowNodes
     * @return Boolean
     * @author lei
     */

    private Boolean addFlowNode(List<FlowNodeVo> flowNodes,final Long flowId) {
        //排序
        List<FlowNode> flowNodeEntitys = flowNodes.stream().sorted(Comparator.comparing(FlowNodeVo::getOrderBy)).map(f -> {
            FlowNode flowNode = new FlowNode();
            BeanUtils.copyProperties(f, flowNode);
            flowNode.setUserIds(f.getUsers().stream().map(ConsumerVo::getUserId).collect(Collectors.toList()));
            flowNode.setFlowId(flowId);
            return flowNode;
        }).collect(Collectors.toList());

        //初始化，挂头结点
        FlowNode head = initHeadNode(flowNodeEntitys.get(0).getOrderBy(), flowId);
        flowNodeEntitys.add(0, head);

        /**
         * 此处考虑到存在id关联，采用两次维护，第一次存储，第二次处理id关联，然后更新，此种存在事务的重入问题？
         * 猜想：1.第一次维护，开启事务，操作库成功，第二次维护，同一事务，再次编辑，锁数据时间过长，
         *      2.单条维护，维护一次提交一次，产生的问题同上，
         *    暂未寻找到跟好的解决办法，故目前采用第一种方案
         */
        return tranManager.exe(() -> {
            //存储
           boolean nodeSaveOk= flowNodeService.saveBatch(flowNodeEntitys);
            //节点和用户关系维护
            List<FlowNodeUser> flowNodeUsersAll = new ArrayList<>();
            for (int i = 0; i < flowNodeEntitys.size(); i++) {
                if (i != 0) {
                    //维护首节点
                    flowNodeEntitys.get(i).setPreNodeId(flowNodeEntitys.get(i - 1).getId());
                }
                if (i != flowNodeEntitys.size() - 1) {
                    //维护末节点
                    flowNodeEntitys.get(i).setNextNodeId(flowNodeEntitys.get(i + 1).getId());

                }
                //维护节点间的用户关系
                List<String> flowNodeUsers = flowNodeEntitys.get(i).getUserIds();
                for (String userId : flowNodeUsers) {
                    FlowNodeUser flowNodeUser = new FlowNodeUser();
                    flowNodeUser.setNodeId(flowNodeEntitys.get(i).getId());
                    flowNodeUser.setUserId(userId);
                    flowNodeUsersAll.add(flowNodeUser);
                }
            }
            //更新关联id
            //维护关联表
            //修改上下节点的关系
            return nodeSaveOk && flowNodeUserService.saveBatch(flowNodeUsersAll) && flowNodeService.updateBatchById(flowNodeEntitys);
        });


    }

    /**
     * 给每一个链表首部挂一个头
     * @param nextNodeOrderBy 下一节点的排序
     * @param flowId 此节点所属流程id
     * @param nodeName 节点名称 默认  ‘发起申请’
     * @return cn.zero.flowspringbootstater.modular.entity.FlowNode
     * @author lei
     */

    private   FlowNode initHeadNode(final Long nextNodeOrderBy,final  Long flowId,final  String nodeName) {
        //初始化首节点名称
        FlowNode head = new FlowNode();
        head.setFlowId(flowId);
        head.setNextNodeId(nextNodeOrderBy);
        head.setNodeName(nodeName);
        head.setOrderBy(nextNodeOrderBy - 1);
        //此处设想当前登录人为发起人
        FLowUser currentUser = getCurrentUser();
        head.setCreatedBy(currentUser.getUserId());
        head.setCreatedTime(LocalDateTime.now());
        head.setUserIds(new ArrayList<String>() {{
            add(currentUser.getUserId());
        }});
        return head;
    }
    /**
     * 给每一个链表首部挂一个头
     * @param nextNodeOrderBy 下一节点的排序
     * @param flowId 此节点所属流程id
     * @return cn.zero.flowspringbootstater.modular.entity.FlowNode
     * @author lei
     */
    private   FlowNode initHeadNode(final Long nextNodeOrderBy,final  Long flowId )  {
        //初始化首节点名称
       return initHeadNode(nextNodeOrderBy, flowId, "发起申请");
    }


    /**
     * 修改流程
     * @param flowParamVo
     * @return java.lang.Long
     * @author lei
     */

    private Long updateFlow(FlowParamVo flowParamVo) throws FlowErrorException {
        Long id = flowParamVo.getId();
        List<FlowNodeVo> flowNodes = flowParamVo.getFlowNodes();

        //校验存在性

        Flow oldFlow = this.lambdaQuery().eq(Flow::getId, id).eq(Flow::getDel, SysConstant.whether.No).orderByDesc(Flow::getVersion).last("limit 1").oneOpt().orElseThrow(() -> new FlowErrorException("流程不存在或被删除"));

        Flow flow = CopyUtil.copyBean(flowParamVo, Flow::new);

        //仅仅修改流程信息，不做流程上的更改，则不动版本号
        if (flowNodes==null||flowNodes.size()==0)
        {
            flow.setFlowCode(null);
            flow.setVersion(null);
            this.lambdaUpdate().eq(Flow::getId, id).eq(Flow::getDel, SysConstant.whether.No).update(flow);
            return id;
        }
        //修改流程
        {
            //版本号++
            flow.setVersion(oldFlow.getVersion()+1);
            flow.setDel(SysConstant.whether.No);
            flow.setStatus(SysConstant.whether.No);

            //原来的设置为删除并禁用（维护原来的快照供当前使用此流程的业务流转完成，）
            oldFlow.setDel(SysConstant.whether.Yes);
            oldFlow.setStatus(SysConstant.whether.Yes);
        }
       tranManager.exe(() -> {
            //修改node信息
            return save(flow) && updateById(oldFlow) && addFlowNode(flowNodes, flow.getId());
        });
        return flow.getId();
    }
    /**
     * 添加
     * 流程做了快照
     * @param flowParamVo 审批流程所需的参数
     * @return: Result 返回新增修改之后的流程id
     * @author: lei
     */

    private Long addFlow(FlowParamVo flowParamVo) throws FlowErrorException {

        //查看是否存在相同名称的流程
        Flow exist = this.lambdaQuery().eq(Flow::getFlowName, flowParamVo.getFlowName()).eq(Flow::getDel,SysConstant.whether.No).last("limit 1").one();
        if (exist != null) {
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "流程名称重复，请修改名称后重新添加");
        }
        //校验是否参数包含node信息
        List<FlowNodeVo> flowNodes = flowParamVo.getFlowNodes();
        if (flowNodes==null||flowNodes.size()==0){
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "请配置流程审批节点！");
        }


        //新增流程
        //初始化流程信息
        Flow flow = CopyUtil.copyBean(flowParamVo, Flow::new);
        {
            //默认不删除
            flow.setDel(StringUtils.isBlank(flowParamVo.getDel())?SysConstant.whether.No:flowParamVo.getDel());
            //默认启用
            flow.setStatus(StringUtils.isBlank(flowParamVo.getStatus()) ? SysConstant.whether.Yes : flowParamVo.getStatus());
            //默认版本
            flow.setVersion(1L);
            //流程编号
            flow.setFlowCode(idFactory.createCode("FL", this.getClass().getName()));
        }
        tranManager.exe(() -> {
            //保存流程信息
            //新增节点
            return this.save(flow) && addFlowNode(flowNodes, flow.getId());
        });
        return flow.getId();
    }

    /**
     * 查询审批流程的审批节点和审批状态详情
     *
     * @param flowId     : 流程id
     * @param businessId : 业务id
     * @return: void
     * @author: lei
     */
    @Override
    public FlowBusinessVo getFlowNodeDetail(String flowId, String businessId) {

        FlowBusinessVo flowBusinessVo = new FlowBusinessVo();
        FlowBusiness resource = flowBusinessService.lambdaQuery().eq(FlowBusiness::getBusinessId, businessId).eq(FlowBusiness::getFlowId, flowId).last("limit 1").one();
        if (resource == null)
            return null;
        BeanUtils.copyProperties(resource, flowBusinessVo);
        if (Constrants.FlowState.OVER_APPRPVAL.equals(resource.getFlowState()))
            flowBusinessVo.setOver(Boolean.TRUE);
        List<FlowEventReVo> flowEventReVos = this.getBaseMapper().selectNodeDetail(flowId, businessId,userConfiguration);
        flowBusinessVo.setFlowEventReVos(flowEventReVos);
        return flowBusinessVo;
    }

    /**
     * 查询流程列表
     *
     * @param flow:
     * @return: java.util.List<cn.ygkj.system.entity.Flow>
     * @author: lei
     */
    @Override
    public Page<Flow> selectFlowList(Flow flow, Integer pageSize, Integer pageNum) {
        Page<Flow> flowPage = new Page<>();
        int count = this.getBaseMapper().selectLFlowListPageCount(flow);
        if (count == 0) {
            flowPage.setRecords(null);
            flowPage.setTotal(0);
        }

        List<Flow> flows = this.getBaseMapper().selectLFlowList(flow, pageSize, --pageNum);
        flowPage.setRecords(flows);
        flowPage.setTotal(count);
        return flowPage;
    }

    /**
     * 获取流程的详情
     *
     * @param id 流程id
     * @return: cn.ygkj.logistics.common.core.utils.Result
     * @author: lei
     */
    @Override
    public List<FlowParamVo> getFlowDetail(Long id) throws FlowErrorException {
        Flow flow = this.lambdaQuery().eq(Flow::getId, id).one();
        Optional.ofNullable(flow).orElseThrow(() -> new FlowErrorException("流程不存在"));
        return this.getBaseMapper().selectFlowDetail(id,userConfiguration);
    }

    @Override
    public List<FlowNode2UserVo> getHasRoleUserIdByBusinessId(Set<String> businessId) {
        return this.getBaseMapper().getHasRoleUserIdByBusinessId(businessId);
    }


    /**
     * 回滚至此业务的上一步，若从已经审批的中间开始回滚，将回滚至{ nodeId }的上一步
     * 如果不传 { nodeId } 则回滚至初始状态
     *
     * @param businesId 业务id
     * @param nodeId    当前的节点id
     * @return cn.ygkj.common.core.model.Result<java.lang.Boolean>
     * @author lei
     */
    @Override
    public Boolean rollbackPrevious(String businesId, Long flowId, Long nodeId) {
        return tranManager.exe(() -> {
            //修改对应业务数据的审批状态为0
            flowBusinessService.lambdaUpdate()
                    .eq(FlowBusiness::getBusinessId, businesId)
                    .eq(FlowBusiness::getFlowId, flowId)
                    .set(FlowBusiness::getFlowState, Constrants.FlowState.UNDER_APPROVAL)
                    .set(nodeId != null, FlowBusiness::getCurrentNodeId, nodeId)
                    .update();
            if (nodeId == null) {
                //重置审批到初始状态
                return resetFlow(businesId, flowId);
            }

            //通过业务id和节点id将此次审批事件废除
            return flowEventsMapper.updateEventState(flowId, nodeId) > 0;
        });
    }

    @Override
    public Boolean resetFlow(String businessId, Long flowId)   {
        FlowBusiness exist = flowBusinessService.lambdaQuery()
                .eq(FlowBusiness::getBusinessId, businessId)
                .eq(FlowBusiness::getFlowId, flowId)
                .eq(FlowBusiness::getState, SysConstant.whether.Yes).one();
        Long id = exist.getId();
        return tranManager.exe(() -> {
            boolean update = flowBusinessService.lambdaUpdate().eq(FlowBusiness::getId, id)
                    .set(FlowBusiness::getState, SysConstant.whether.No).update();
            //事件表删除
            int total = flowEventsMapper.updateByFowId2BusinessId(businessId, flowId, SysConstant.whether.No);
            return update && total > 0;
        });
    }

    /**
     * 校验参数
     *
     * @param param:
     * @return: void
     * @author: lei
     */

    private static void checkParams(FlowBindDto param) throws FlowErrorException{
        if (param == null)
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "参数不能为空");

        if (StringUtils.isBlank(param.getBusinessId()))
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "businessId不能为空");

        if (param.getFlowId() == null)
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "flowId不能为空");
        if (param.getInitUserId() == null)
            throw new FlowErrorException(HttpStatus.BAD_REQUEST, "绑定用户id不能为空");

    }

    /**
     * 校验
     * @param t 校验的目标对象
     * @param con 校验规则集合
     * @return boolean 是否无法被任何规则命中
     * @author lei
     */

    private static <T> boolean judgeByPredicate(T t,Map<Object,Predicate<T>> con) {
        Set<Object> keys = con.keySet();
        //匹配到其中一个则返回false
        return keys.stream().noneMatch(f ->con.get(f).test(t));
    }


    /**
     * 检测是否实现获取当前登录用户的方法
     *
     * @return void
     * @author lei
     */


    @Override
    public void afterPropertiesSet() throws Exception {
        FLowUser currentUser = getCurrentUser();
    }
}
